{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 数据挖掘 作业3 分类、预测与聚类\n",
    "\n",
    "## 任务：基于支持向量机的手写数字识别\n",
    "\n",
    "**姓名：陈康冰**\n",
    "\n",
    "**学号：3220220897**"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**代码仓库地址：** https://gitee.com/ckblau/dm2023-homework"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from mlxtend.data import loadlocal_mnist\n",
    "from sklearn import svm, metrics\n",
    "import torch\n",
    "import torchvision"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. 读取 MNIST 数据\n",
    "\n",
    "加载并处理手写数字图像数据及其对应的标签。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(60000, 784) (60000,)\n"
     ]
    }
   ],
   "source": [
    "path = ['train-images.idx3-ubyte','train-labels.idx1-ubyte', 't10k-images.idx3-ubyte','t10k-labels.idx1-ubyte']\n",
    "\n",
    "X, y = loadlocal_mnist(path[0], path[1])\n",
    "print(X.shape, y.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,\n",
       "         18,  18,  18, 126, 136, 175,  26, 166, 255, 247, 127,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,  30,  36,  94, 154, 170,\n",
       "        253, 253, 253, 253, 253, 225, 172, 253, 242, 195,  64,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,  49, 238, 253, 253, 253, 253,\n",
       "        253, 253, 253, 253, 251,  93,  82,  82,  56,  39,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,  18, 219, 253, 253, 253, 253,\n",
       "        253, 198, 182, 247, 241,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,  80, 156, 107, 253, 253,\n",
       "        205,  11,   0,  43, 154,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,  14,   1, 154, 253,\n",
       "         90,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 139, 253,\n",
       "        190,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  11, 190,\n",
       "        253,  70,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  35,\n",
       "        241, 225, 160, 108,   1,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "         81, 240, 253, 253, 119,  25,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,  45, 186, 253, 253, 150,  27,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0,  16,  93, 252, 253, 187,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0,   0,   0, 249, 253, 249,  64,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,  46, 130, 183, 253, 253, 207,   2,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  39,\n",
       "        148, 229, 253, 253, 253, 250, 182,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  24, 114, 221,\n",
       "        253, 253, 253, 253, 201,  78,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,  23,  66, 213, 253, 253,\n",
       "        253, 253, 198,  81,   2,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,  18, 171, 219, 253, 253, 253, 253,\n",
       "        195,  80,   9,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,  55, 172, 226, 253, 253, 253, 253, 244, 133,\n",
       "         11,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0, 136, 253, 253, 253, 212, 135, 132,  16,   0,\n",
       "          0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0],\n",
       "       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "          0,   0]], dtype=uint8)"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X[0].reshape(28, 28)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5, 0, 4, ..., 5, 6, 8], dtype=uint8)"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x1b271d46b00>"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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AGCGCAEAzBAhAIAZIgQAMEOEAABmiBAAwAwRAgCYIUIAADNECABghggBAMwQIQCAGSIEADBDhAAAZogQAMAMEQIAmCFCAAAzRAgAYIYIAQDMECEAgBkiBAAwQ4QAAGaIEADADBECAJghQgAAM0QIAGBmqPUCruWckyT16JLkjBcDAPDWo0uS/v9/z/vS7yLU1dUlSXpDe41XAgD4PLq6uhQOh/vcJuB+n1TdQpcvX9aZM2cUCoUUCARSXovH4youLlZra6vy8vKMVmiP43AFx+EKjsMVHIcr+sNxcM6pq6tLRUVFuu22vt/16XdXQrfddpvGjBnT5zZ5eXmD+iS7iuNwBcfhCo7DFRyHK6yPw82ugK7igwkAADNECABgJqciFAwGtWbNGgWDQeulmOI4XMFxuILjcAXH4YpcOw797oMJAIDBI6euhAAAAwsRAgCYIUIAADNECABgJqci9MILL6i0tFS33367Jk2apNdff916SbdUTU2NAoFAyiMSiVgvK+sOHjyoBQsWqKioSIFAQLt27Up53TmnmpoaFRUVacSIESovL9fx48dtFptFNzsOS5cuve78mDZtms1is6S2tlZTpkxRKBRSQUGBFi5cqBMnTqRsMxjOh9/nOOTK+ZAzEdqxY4dWrFih1atX6+jRo7r33ntVWVmp06dPWy/tlho/frza2tqSj2PHjlkvKeu6u7s1ceJE1dXV3fD1devWaf369aqrq1NTU5MikYjmzZuXvA/hQHGz4yBJ8+fPTzk/9u4dWPdgbGxsVFVVlQ4fPqz6+nr19PSooqJC3d3dyW0Gw/nw+xwHKUfOB5cjvvrVr7rHH3885bm7777bffe73zVa0a23Zs0aN3HiROtlmJLkXn755eTXly9fdpFIxD377LPJ5z755BMXDofdj3/8Y4MV3hrXHgfnnFuyZIm7//77TdZjpaOjw0lyjY2NzrnBez5cexycy53zISeuhC5evKgjR46ooqIi5fmKigodOnTIaFU2mpubVVRUpNLSUj300EM6efKk9ZJMtbS0qL29PeXcCAaDmj179qA7NySpoaFBBQUFGjdunB599FF1dHRYLymrYrGYJCk/P1/S4D0frj0OV+XC+ZATETp79qx6e3tVWFiY8nxhYaHa29uNVnXrTZ06VVu2bNG+ffv04osvqr29XTNmzFBnZ6f10sxc/ec/2M8NSaqsrNTWrVu1f/9+Pffcc2pqatLcuXOVSCSsl5YVzjlVV1dr5syZKisrkzQ4z4cbHQcpd86HfncX7b5c+6MdnHPXPTeQVVZWJn89YcIETZ8+XXfddZc2b96s6upqw5XZG+znhiQtXrw4+euysjJNnjxZJSUl2rNnjxYtWmS4suxYtmyZ3n33Xb3xxhvXvTaYzofPOg65cj7kxJXQ6NGjNWTIkOv+T6ajo+O6/+MZTEaNGqUJEyaoubnZeilmrn46kHPjetFoVCUlJQPy/Fi+fLl2796tAwcOpPzol8F2PnzWcbiR/no+5ESEhg8frkmTJqm+vj7l+fr6es2YMcNoVfYSiYTee+89RaNR66WYKS0tVSQSSTk3Ll68qMbGxkF9bkhSZ2enWltbB9T54ZzTsmXLtHPnTu3fv1+lpaUprw+W8+Fmx+FG+u35YPihCC/bt293w4YNcz/96U/dr3/9a7dixQo3atQod+rUKeul3TIrV650DQ0N7uTJk+7w4cPuvvvuc6FQaMAfg66uLnf06FF39OhRJ8mtX7/eHT161P32t791zjn37LPPunA47Hbu3OmOHTvmHn74YReNRl08HjdeeWb1dRy6urrcypUr3aFDh1xLS4s7cOCAmz59uvvCF74woI7DE0884cLhsGtoaHBtbW3Jx8cff5zcZjCcDzc7Drl0PuRMhJxz7vnnn3clJSVu+PDh7itf+UrKxxEHg8WLF7toNOqGDRvmioqK3KJFi9zx48etl5V1Bw4ccJKueyxZssQ5d+VjuWvWrHGRSMQFg0E3a9Ysd+zYMdtFZ0Ffx+Hjjz92FRUV7o477nDDhg1zd955p1uyZIk7ffq09bIz6kZ/fklu06ZNyW0Gw/lws+OQS+cDP8oBAGAmJ94TAgAMTEQIAGCGCAEAzBAhAIAZIgQAMEOEAABmiBAAwAwRAgCYIUIAADNECABghggBAMwQIQCAmf8Lw4IYymq+HboAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(X[0].reshape(28, 28))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 划分训练集和测试集\n",
    "\n",
    "将图像数据划分为训练集和测试集，比例一般为7:3或8:2。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里采用 训练集:测试集 = 8:2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(48000, 784) (48000,)\n",
      "(12000, 784) (12000,)\n"
     ]
    }
   ],
   "source": [
    "train_size = int(len(X) * 0.8)\n",
    "trainX = X[:train_size]\n",
    "trainy = y[:train_size]\n",
    "print(trainX.shape, trainy.shape)\n",
    "testX = X[train_size:]\n",
    "testy = y[train_size:]\n",
    "print(testX.shape, testy.shape)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. 特征缩放\n",
    "\n",
    "对图像数据进行归一化处理，缩放到[0,1]范围。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [],
   "source": [
    "trainX = trainX / 256\n",
    "trainy = trainy.astype(int)\n",
    "testX = testX / 256\n",
    "testy = testy.astype(int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.01171875, 0.0703125 , 0.0703125 ,\n",
       "       0.0703125 , 0.4921875 , 0.53125   , 0.68359375, 0.1015625 ,\n",
       "       0.6484375 , 0.99609375, 0.96484375, 0.49609375, 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.1171875 , 0.140625  , 0.3671875 , 0.6015625 ,\n",
       "       0.6640625 , 0.98828125, 0.98828125, 0.98828125, 0.98828125,\n",
       "       0.98828125, 0.87890625, 0.671875  , 0.98828125, 0.9453125 ,\n",
       "       0.76171875, 0.25      , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.19140625, 0.9296875 ,\n",
       "       0.98828125, 0.98828125, 0.98828125, 0.98828125, 0.98828125,\n",
       "       0.98828125, 0.98828125, 0.98828125, 0.98046875, 0.36328125,\n",
       "       0.3203125 , 0.3203125 , 0.21875   , 0.15234375, 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.0703125 , 0.85546875, 0.98828125, 0.98828125,\n",
       "       0.98828125, 0.98828125, 0.98828125, 0.7734375 , 0.7109375 ,\n",
       "       0.96484375, 0.94140625, 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.3125    , 0.609375  , 0.41796875, 0.98828125, 0.98828125,\n",
       "       0.80078125, 0.04296875, 0.        , 0.16796875, 0.6015625 ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.0546875 ,\n",
       "       0.00390625, 0.6015625 , 0.98828125, 0.3515625 , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.54296875,\n",
       "       0.98828125, 0.7421875 , 0.0078125 , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.04296875, 0.7421875 , 0.98828125,\n",
       "       0.2734375 , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.13671875, 0.94140625, 0.87890625, 0.625     ,\n",
       "       0.421875  , 0.00390625, 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.31640625, 0.9375    , 0.98828125, 0.98828125, 0.46484375,\n",
       "       0.09765625, 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.17578125,\n",
       "       0.7265625 , 0.98828125, 0.98828125, 0.5859375 , 0.10546875,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.0625    , 0.36328125,\n",
       "       0.984375  , 0.98828125, 0.73046875, 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.97265625, 0.98828125,\n",
       "       0.97265625, 0.25      , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.1796875 , 0.5078125 ,\n",
       "       0.71484375, 0.98828125, 0.98828125, 0.80859375, 0.0078125 ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.15234375,\n",
       "       0.578125  , 0.89453125, 0.98828125, 0.98828125, 0.98828125,\n",
       "       0.9765625 , 0.7109375 , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.09375   , 0.4453125 , 0.86328125, 0.98828125, 0.98828125,\n",
       "       0.98828125, 0.98828125, 0.78515625, 0.3046875 , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.08984375, 0.2578125 , 0.83203125, 0.98828125,\n",
       "       0.98828125, 0.98828125, 0.98828125, 0.7734375 , 0.31640625,\n",
       "       0.0078125 , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.0703125 , 0.66796875, 0.85546875,\n",
       "       0.98828125, 0.98828125, 0.98828125, 0.98828125, 0.76171875,\n",
       "       0.3125    , 0.03515625, 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.21484375, 0.671875  ,\n",
       "       0.8828125 , 0.98828125, 0.98828125, 0.98828125, 0.98828125,\n",
       "       0.953125  , 0.51953125, 0.04296875, 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.53125   , 0.98828125, 0.98828125, 0.98828125,\n",
       "       0.828125  , 0.52734375, 0.515625  , 0.0625    , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
       "       0.        , 0.        , 0.        , 0.        ])"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "trainX[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5, 0, 4, ..., 0, 1, 2])"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "trainy"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. 构建支持向量机模型\n",
    "\n",
    "选择适当的核函数（如线性核、多项式核、径向基核等），训练模型。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里选择径向基函数作为SVM的核函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train():\n",
    "    model_svc = svm.SVC(kernel='rbf', gamma='scale')\n",
    "    model_svc.fit(trainX, trainy)\n",
    "    return model_svc"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对模型进行训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = train()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. 模型评估\n",
    "\n",
    "在测试集上进行预测，计算模型的准确率、召回率、F1值等指标，评估模型性能。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用测试集对模型进行测试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test(model):\n",
    "    print(model.score(testX, testy))  \n",
    "    y_pred = model.predict(testX)\n",
    "    print(\"准确率： %.6f\" % metrics.accuracy_score(testy,y_pred))\n",
    "    print(\"F1-score: %.6f\" % metrics.f1_score(testy,y_pred,average='macro'))\n",
    "    print(\"召回率： %.6f\" % metrics.recall_score(testy,y_pred,average='macro'))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "计算模型指标，即可对模型性能进行评估"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.9785833333333334\n",
      "准确率： 0.978583\n",
      "F1-score: 0.978358\n",
      "召回率： 0.978327\n"
     ]
    }
   ],
   "source": [
    "test(model)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.9"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
